////////////////////////////////////////////////////////////////////
// Programme de compression/décompression CPT pour Chrono Cross
////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////
// Nemesis pour Terminus Traduction (tt_nemesis@yahoo.fr)
// Date de création :		05/08/03
// Dernière modification :	29/05/04
////////////////////////////////////////////////////////////////////

// Entete
#include "Patcheur.h"

int fichs_nb;

/*------------------------------------------------------------------
  Décompression CPT d'un fichier
--------------------------------------------------------------------
 <- fich : fichier CPT à décompresser
------------------------------------------------------------------*/
JNIEXPORT jint JNICALL Java_Librairie_cpt_1decompression
  (JNIEnv *env, jclass cl, jstring fichier)
{
	const char *fich = env->GetStringUTFChars(fichier,0);

	// Fichier Cpt à décompresser
	FILE *cpt_f;
	char cpt_nom[FICH_MAX];
	// Fichier de sortie
	FILE *out_f;
	char dir_nom[FICH_MAX];
	char out_nom[FICH_MAX];
	// Adresses des fichiers
	int adresses[NB_MAX];
	// Index des fichiers
	int f;
	// Position d'arrêt de copie
	int pos;
	// Buffer
	char buffer[BUFFER];

	// Ouverture du fichier CPT
	sprintf(cpt_nom,"%s\\%s",DIR_BASE,fich);
	cpt_f=fopen(cpt_nom,"rb");

	// Fichier existant ?
	if (cpt_f==NULL)
		return ERROR_FILE;

	// Creation du dossier de sortie
	sprintf(dir_nom,"%s\\%s%s",DIR_BASE,fich,DIR_SUFF);
	if (mkdir(dir_nom)!=0 && errno==ENOENT)
		return ERROR_DIR;

	// Lecture du nombre de fichiers
	fread(&fichs_nb,sizeof(_int32),1,cpt_f);
	// Trop de fichiers ?
	if (fichs_nb>=NB_MAX)
		return ERROR_OVER;

	// Chargement des adresses
	for(f=0;f<=fichs_nb;f++)
		fread(&adresses[f],sizeof(int),1,cpt_f);
	// Décompression des fichiers
	for(f=0;f<fichs_nb;f++) {
		// Ouverture du fichier extrait
		sprintf(out_nom,"%s\\%04d",dir_nom,f);
		out_f=fopen(out_nom,"wb");
		if (out_f==NULL)
			return ERROR_FILE;

		// Placement dans le fichier compacté
		fseek(cpt_f,adresses[f],SEEK_SET);
		// Extraction du fichier
		for(pos=adresses[f];
			pos<=adresses[f+1]-BUFFER;
			pos+=BUFFER)
		{
			fread(buffer,sizeof(char),BUFFER,cpt_f);
			fwrite(&buffer,sizeof(char),BUFFER,out_f);
		}
		// Attention à l'ordre pour
		// rester dans les positifs
		pos=(adresses[f+1]-adresses[f])%BUFFER;
		fread(buffer,sizeof(char),pos,cpt_f);
		fwrite(&buffer,sizeof(char),pos,out_f);
		// Fermeture du fichier extrait
		fclose(out_f);
	}
	// Fermeture du CPT
	fclose(cpt_f);
	// Suppression du fichier
	remove(cpt_nom);

	return ERROR_NONE;
}

/*------------------------------------------------------------------
  Compression CPT de fichiers
--------------------------------------------------------------------
 <- fich : fichier CPT à compresser
 (on suppose que le nombre de fichiers est mémorisé lors de
  la décompression => interdiction de faire Cpt_D, Cpt_D, Cpt_C)
------------------------------------------------------------------*/
JNIEXPORT jint JNICALL Java_Librairie_cpt_1compression
  (JNIEnv *env, jclass cl, jstring fichier)
{
	const char *fich = env->GetStringUTFChars(fichier,0);

	// Fichier Cpt
	FILE *cpt_f;
	char cpt_nom[FICH_MAX];
	// Fichiers d'entrée
	FILE *in_f;
	char in_nom[FICH_MAX];
	// Adresses des fichiers
	int adresses[NB_MAX];
	// Index des fichiers
	int f;
	// Buffer
	char buffer[BUFFER];
	// Nombre d'octets lus
	int result;

	// Ouverture du fichier CPT
	sprintf(cpt_nom,"%s\\%s",DIR_BASE,fich);
	cpt_f=fopen(cpt_nom,"wb");

	// Fichier créé ?
	if (cpt_f==NULL)
		return ERROR_FILE;

	// Changement de dossier
	sprintf(cpt_nom,"%s\\%s%s",DIR_BASE,fich,DIR_SUFF);

	// Ecriture du nombre de fichiers
	fwrite(&fichs_nb,sizeof(int),1,cpt_f);

	// Saut au niveau du premier fichier
	fseek(cpt_f,(fichs_nb+2)*sizeof(int),SEEK_SET);
	// Recompression des fichiers
	for(f=0;f<fichs_nb;f++) {
		adresses[f]=ftell(cpt_f);
		// Complétion du fichier source
		sprintf(in_nom,"%s\\%04d",cpt_nom,f);
		Fichier_Completer(in_nom);
		// Ouverture du fichier à réinsérer
		in_f=fopen(in_nom,"rb");
		if (in_f==NULL)
			return ERROR_FILE;

		// Copie des données
		while((result=fread(buffer,sizeof(char),BUFFER,in_f))>0)
			fwrite(&buffer,sizeof(char),result,cpt_f);
		// Fermeture du fichier extrait
		fclose(in_f);
		// Suppression du fichier
		remove(in_nom);
	}
	adresses[f]=ftell(cpt_f);
	// Retour au début
	fseek(cpt_f,sizeof(int),SEEK_SET);
	// Ecriture des adresses
	for (f=0;f<fichs_nb+1;f++)
		fwrite(&adresses[f],sizeof(int),1,cpt_f);
	// Fermeture du fichier
	fclose(cpt_f);
	// Suppression du dossier
	rmdir(cpt_nom);

	return ERROR_NONE;
}